// ------------------------------------------------------------------------------------------------
// File   : DX9VertexShader.h
// Date   : 2012-08-01
// Author : Weng xiao yi
// Rev.   : 
// Descr. : 
// ------------------------------------------------------------------------------------------------

#ifndef OY_DX9VERTEXSHADER_H
#define OY_DX9VERTEXSHADER_H

#include "DX9Shader.h"
// vertex shader definition ----------------------------------------

enum DX9VSGlobalConstant 
{
	VS_GLOBAL_CONSTANT_WORLDVIEWPROJ,


	VS_GLOBAL_CONSTANT_FOG_NORMALIZEWDEPTH,
	VS_GLOBAL_CONSTANT_FOG_RAMPSCALE,
	VS_GLOBAL_CONSTANT_FOG_DITHERCONTROL,
	VS_GLOBAL_CONSTANT_FOG_HALFTEXELSIZE,
	VS_GLOBAL_CONSTANT_FOG_NOISE_UVBIAS,
	VS_GLOBAL_CONSTANT_FOG_NOISE_UVSCALE,
	VS_GLOBAL_CONSTANT_FOG_VOLUME_CENTER,
	VS_GLOBAL_CONSTANT_FOG_VOLUME_SCALE,



	VS_GLOBAL_CONSTANT_RADIAL_BLUR,
	VS_GLOBAL_CONSTANT_SCREEN_RESOLUTION,
	VS_GLOBAL_CONSTANT_BLURDIRECTION,
	VS_GLOBAL_CONSTANT_BLURWIDTH,

	VS_GLOBAL_CONSTANT_CIRCLECENTER,
	VS_GLOBAL_CONSTANT_CIRCLETEXSCALE,


	VS_GLOBAL_CONSTANT_CAMERAPOS,
	VS_GLOBAL_CONSTANT_LIGHTPOS,
	VS_GLOBAL_CONSTANT_ADVWATERPARAMS,
	VS_GLOBAL_CONSTANT_ADVWATERDIR,

	VS_GLOBAL_CONSTANT_WEATHER_WVPPREV,
	VS_GLOBAL_CONSTANT_WEATHER_POSITIONOFFSET,
	VS_GLOBAL_CONSTANT_WEATHER_VELOCITY,
	VS_GLOBAL_CONSTANT_WEATHER_ALPHA,
	VS_GLOBAL_CONSTANT_WEATHER_VIEWPOS,
	VS_GLOBAL_CONSTANT_WEATHER_SIZESCALE,
	VS_GLOBAL_CONSTANT_WEATHER_LIGHTING,
	VS_GLOBAL_CONSTANT_WEATHER_FORWARD,


	VS_GLOBAL_CONSTANT_COUNT
};

// vertex shader global constant HLSL names
const char g_aszVSGlobalConstName[VS_GLOBAL_CONSTANT_COUNT][32] = {

	"g_mWorldViewProj",						// VS_GLOBAL_CONSTANT_WORLDVIEWPROJ

	"g_vFogNormalizeWDepth",                // VS_GLOBAL_CONSTANT_FOG_NORMALIZEWDEPTH
	"g_vFogRampScale",                      // VS_GLOBAL_CONSTANT_FOG_RAMPSCALE
	"g_vFogDitherControl",					// VS_GLOBAL_CONSTANT_FOG_DITHERCONTROL
	"g_vFogHalfTexelSize",					// VS_GLOBAL_CONSTANT_FOG_HALFTEXELSIZE
	"g_vFogNoiseUVBias",					// VS_GLOBAL_CONSTANT_FOG_NOISE_UVBIAS
	"g_vFogNoiseUVScale",					// VS_GLOBAL_CONSTANT_FOG_NOISE_UVSCALE
	"g_vFogVolumeCenter",					// VS_GLOBAL_CONSTANT_FOG_VOLUME_CENTER
	"g_vFogVolumeScale",					// VS_GLOBAL_CONSTANT_FOG_VOLUME_SCALE


	"g_fRadialBlurFactor",              // VS_GLOBAL_CONSTANT_RADIAL_BLUR
	"g_vScreenResolution",              // VS_GLOBAL_CONSTANT_SCREEN_RESOLUTION
	"g_vBlurDirection",					// VS_GLOBAL_CONSTANT_BLURDIRECTION
	"g_fBlurWidth",						// VS_GLOBAL_CONSTANT_BLURWIDTH
	"g_vCircleCenter",					// VS_GLOBAL_CONSTANT_CIRCLECENTER
	"g_vTexcoordScale",					// VS_GLOBAL_CONSTANT_CIRCLETEXSCALE

	"g_vCameraPos",							//VS_GLOBAL_CONSTANT_CAMERAPOS,
	"g_vLightPos",							//VS_GLOBAL_CONSTANT_LIGHTPOS,
	"g_vWaveParams",						//VS_GLOBAL_CONSTANT_ADVWATERPARAMS,
	"g_vWaveDir",							//VS_GLOBAL_CONSTANT_ADVWATERDIR

	//
	"g_mWorldViewProjPrev",					//VS_GLOBAL_CONSTANT_WEATHER_WVPPREV
	"g_vPositionOffset",					//VS_GLOBAL_CONSTANT_WEATHER_POSITIONOFFSET
	"g_vVelocity",							//VS_GLOBAL_CONSTANT_WEATHER_VELOCITY
	"g_vAlpha",								//VS_GLOBAL_CONSTANT_WEATHER_ALPHA
	"g_vViewPosition",						//VS_GLOBAL_CONSTANT_WEATHER_VIEWPOS
	"g_vSizeScale",							//VS_GLOBAL_CONSTANT_WEATHER_SIZESCALE
	"g_vLighting",							//VS_GLOBAL_CONSTANT_WEATHER_LIGHTING
	"g_vForward",							//VS_GLOBAL_CONSTANT_WEATHER_FORWARD
};

class DX9VertexShader : public DX9Shader<LPDIRECT3DVERTEXSHADER9 , VS_GLOBAL_CONSTANT_COUNT>
{
public:

	DX9VertexShader() {}

	inline BOOL ReInit(const DWORD *_pShaderStream, BOOL bAssembleShader = FALSE);

	inline DX9VertexShader*  Duplicate(void) const;
};

BOOL DX9VertexShader::ReInit(const DWORD *_pShaderStream, BOOL bAssembleShader)
{
	HRESULT hr;

	const DWORD * pStream = _pShaderStream;
	const DWORD * pStreamConstantTable = _pShaderStream;

	// create shader interface
	hr = GetD3DDevice()->CreateVertexShader( pStream, &m_pShaderInterface );
	//DX9ValidateRet(SUCCEEDED(hr), FALSE, "Device vertex shader creation failed");

	if(bAssembleShader && m_pConstantTable == NULL)
		return TRUE;

	if(m_pConstantTable == NULL)
	{
		// get constant table
		hr = D3DXGetShaderConstantTable(pStreamConstantTable, &m_pConstantTable);
		if(FAILED(hr))
		{
			// destroy shader interface
			DX9_SAFE_RELEASE(m_pShaderInterface);
			DX9_SAFE_RELEASE(m_pConstantTable);

			return FALSE;
			//DX9ValidateRet(SUCCEEDED(hr), FALSE, "Unable to access a vertex shader's constant table");
		}
	}

	// get all global constant handles
	for(ULONG ulCurGlobalConst = 0; ulCurGlobalConst < VS_GLOBAL_CONSTANT_COUNT; ulCurGlobalConst++)
	{
		m_ahConstant[ulCurGlobalConst] = m_pConstantTable->GetConstantByName(NULL, g_aszVSGlobalConstName[ulCurGlobalConst]);

		if( m_ahConstant[ulCurGlobalConst] )
		{
			D3DXCONSTANT_DESC oDesc;
			UINT uiCount=1;
			hr = m_pConstantTable->GetConstantDesc(m_ahConstant[ulCurGlobalConst], &oDesc, &uiCount);
			DX9Verify( SUCCEEDED(hr) );
			m_lRegister[ulCurGlobalConst] = oDesc.RegisterIndex;
		}
		else
		{
			m_lRegister[ulCurGlobalConst] = -1;
		}
	}

	return TRUE;
}

inline DX9VertexShader* DX9VertexShader::Duplicate(void) const
{
	DX9VertexShader* pNewShader = new DX9VertexShader();

	pNewShader->m_pShaderInterface = m_pShaderInterface;
	pNewShader->m_pConstantTable   = m_pConstantTable;
	pNewShader->m_bAutoGenerated   = m_bAutoGenerated;

	memcpy(pNewShader->m_ahConstant, m_ahConstant, VS_GLOBAL_CONSTANT_COUNT * sizeof(D3DXHANDLE));
	memcpy(pNewShader->m_lRegister,  m_lRegister,  VS_GLOBAL_CONSTANT_COUNT * sizeof(LONG));

	if(pNewShader->m_pShaderInterface != NULL)
	{
		pNewShader->m_pShaderInterface->AddRef();
	}

	if(pNewShader->m_pConstantTable != NULL)
	{
		pNewShader->m_pConstantTable->AddRef();
	}

#if defined(SHADER_DEBUG)
	strcpy_s(pNewShader->m_Filename, m_Filename);
#endif

	pNewShader->m_bIsDefault = m_bIsDefault;

	return pNewShader;
}

#endif // OY_DX9VERTEXSHADER_H